在上一篇文章中,我們認識了JSON的基本語法,包括Object、Array、String、Number及Boolean。
但是,FHIR不只要求資料符合JSON語法,還會進一步規定每個欄位應使用哪一種FHIR資料型別。
例如,以下資料在JSON語法上沒有問題:
{
"birthDate": "我不記得了"
}
birthDate的Value是一個合法的JSON String,但FHIR規定Patient的birthDate必須符合date資料型別,所以「我不記得了」並不是有效的FHIR出生日期。
這表示:
JSON資料型別負責基本語法,FHIR資料型別則進一步規定醫療資料應該如何表達。
今天就來認識FHIR中經常使用的基本型別及複合型別。
如果所有資料都只使用一般文字表示,系統很難正確理解內容。
例如:
{
"result": "60"
}
這個60代表什麼?
它可能是:
如果只交換一個數字,接收方不知道它的測量項目、單位及意義。
FHIR因此定義了不同資料型別,用來表示:
如此一來,系統不只收到Value,也能理解這項Value應該如何被處理。
為了方便初學,可以先將常見FHIR資料型別分成兩類:
基本型別通常只有一個值,例如:
複合型別由多個欄位組成,例如:
要注意FHIR官方命名的大小寫:
string、dateTime。HumanName、Address。接下來先從基本型別開始。
boolean只有兩個值:
true
false
例如Patient的active欄位:
{
"resourceType": "Patient",
"active": true
}
表示這筆Patient紀錄目前有效。
在JSON中,boolean不能加上雙引號,也要使用小寫。
正確:
"active": true
錯誤:
"active": "true"
錯誤:
"active": True
第一個錯誤把Boolean寫成String,第二個錯誤則使用了JSON不接受的大寫形式。
integer用來表示沒有小數點的整數。
例如:
"rank": 1
正確的integer不需要雙引號:
1
如果寫成:
"1"
它就會變成String。
FHIR不同欄位可能對整數範圍有進一步限制。例如,有些欄位只能使用正整數,會使用positiveInt;有些欄位允許0但不允許負數,可能使用unsignedInt。
decimal可以表示整數或包含小數點的數值,例如:
37.2
60
在FHIR中,decimal經常出現在測量數值中,例如體溫、身高及體重。
不過,醫療測量通常不能只放一個decimal,還需要一起記錄測量單位,因此經常會放在Quantity複合型別中。
例如:
"valueQuantity": {
"value": 37.2,
"unit": "°C"
}
string用來表示一般文字,JSON中需要使用雙引號。
例如:
"display": "王小明"
"text": "病人主訴頭暈"
string可以用來提供人類閱讀的內容,但如果資料需要讓電腦進一步分類或比對,通常不能只依靠自由文字。
例如,疾病名稱如果只寫成:
"text": "高血壓"
其他系統可能不知道它對應哪一個標準診斷代碼。
這時就可能需要使用Coding或CodeableConcept。
code在JSON中看起來也是字串:
"gender": "male"
但它和一般string不同。
string通常可以放入較自由的文字;code則通常必須從特定代碼集合中選擇。
例如,Patient的gender在FHIR R4中可以使用:
male
female
other
unknown
不能自行寫成:
"gender": "男"
也不能自行縮寫成:
"gender": "M"
除非規範允許,否則系統應使用FHIR定義的代碼。
uri用來表示統一資源識別碼。
例如Identifier中的system:
"system": "https://hospital.example.org/mrn"
這個URI不是用來表示病歷號本身,而是識別「病歷號屬於哪一套編號系統」。
FHIR中經常使用URI識別:
URI看起來可能像一般網址,但它的主要用途是提供全球唯一或清楚的識別,不代表每一個URI都一定能用瀏覽器開啟。
date用來表示日期。
完整格式通常是:
YYYY-MM-DD
例如:
"birthDate": "2000-01-01"
FHIR date也可以只記錄已知的部分。
只知道年份:
"birthDate": "2000"
只知道年份及月份:
"birthDate": "2000-01"
知道完整日期:
"birthDate": "2000-01-01"
如果來源資料只知道病人出生於2000年,就不應自行補成2000年1月1日,因為這會製造原本不存在的資料。
dateTime可以同時記錄日期及時間。
例如:
"effectiveDateTime": "2026-09-03T09:30:00+08:00"
可以拆成:
| 部分 | 意義 |
|---|---|
2026-09-03 |
日期 |
T |
分隔日期與時間 |
09:30:00 |
時、分、秒 |
+08:00 |
時區 |
臺灣時間通常使用UTC+8,所以範例中使用+08:00。
時間資料如果缺少時區,跨地區或跨系統交換時可能產生誤解。
dateTime適合表示:
| 資料型別 | 內容 | 範例 |
|---|---|---|
| date | 日期 | 2000-01-01 |
| dateTime | 日期及時間 | 2026-09-03T09:30:00+08:00 |
病人的出生日期通常只需要date:
"birthDate": "2000-01-01"
檢驗或生命徵象的量測時間則可能需要dateTime:
"effectiveDateTime": "2026-09-03T09:30:00+08:00"
雖然date與dateTime在JSON中都以String呈現,但FHIR會針對內容格式做更進一步的限制。
Identifier用來表示醫療或行政流程中的識別資料,例如:
範例:
"identifier": [
{
"use": "usual",
"system": "https://hospital.example.org/mrn",
"value": "MRN0001"
}
]
Identifier常見欄位包括:
| 欄位 | 用途 |
|---|---|
use |
識別碼用途 |
type |
識別碼類型 |
system |
識別碼所屬系統 |
value |
實際識別碼 |
period |
識別碼有效期間 |
assigner |
核發識別碼的機構 |
只看value可能不夠。
假設兩家醫院都有病歷號MRN0001,必須搭配不同的system,才能知道它們分別屬於哪家醫院。
HumanName用來表示人的姓名。
範例:
"name": [
{
"use": "official",
"text": "王小明",
"family": "王",
"given": [
"小明"
]
}
]
常見欄位包括:
| 欄位 | 用途 |
|---|---|
use |
姓名用途 |
text |
適合直接顯示的完整姓名 |
family |
姓氏或家族名稱 |
given |
名字 |
prefix |
姓名前綴 |
suffix |
姓名後綴 |
period |
姓名使用期間 |
name通常可以出現多次,因此能同時記錄正式姓名、舊名或暱稱。
FHIR將姓名設計成複合型別,是因為不同國家及文化的姓名結構並不相同。
Address用來表示郵寄地址或實體地址。
範例:
"address": [
{
"use": "home",
"type": "both",
"text": "桃園市中壢區範例路100號",
"city": "中壢區",
"district": "桃園市",
"country": "TW"
}
]
常見欄位包括:
| 欄位 | 用途 |
|---|---|
use |
住家、工作或舊地址等用途 |
type |
郵寄地址、實體地址或兩者皆是 |
text |
完整顯示文字 |
line |
街道及門牌等地址內容 |
city |
城市或地區 |
district |
行政區域 |
state |
州或其他行政區 |
postalCode |
郵遞區號 |
country |
國家 |
period |
地址有效期間 |
由於各國地址格式不同,實際在臺灣使用時仍應參考TW Core IG對地址的規定。
ContactPoint用來表示:
範例:
"telecom": [
{
"system": "phone",
"value": "0900-000-001",
"use": "mobile",
"rank": 1
}
]
常見欄位包括:
| 欄位 | 用途 |
|---|---|
system |
電話、電子郵件或傳真等類型 |
value |
實際聯絡內容 |
use |
住家、工作或行動電話等用途 |
rank |
優先順序 |
period |
有效期間 |
如果病人有多種聯絡方式,可以在telecom Array中放入多個ContactPoint。
Coding用來表示一個來自特定CodeSystem的代碼。
範例:
{
"system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus",
"code": "S",
"display": "Never Married"
}
常見欄位包括:
| 欄位 | 用途 |
|---|---|
system |
代碼系統的識別URI |
version |
代碼系統版本 |
code |
實際代碼 |
display |
方便人類閱讀的名稱 |
userSelected |
是否由使用者直接選擇 |
其中,電腦主要利用system與code辨認概念。
只看到:
"code": "S"
並不能確定它代表什麼,因為不同CodeSystem都可能使用代碼S。
加入system後,接收方才能知道應該到哪一套代碼系統解讀。
CodeableConcept可以包含一個或多個Coding,也可以加入人類可閱讀的text。
範例:
"maritalStatus": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus",
"code": "S",
"display": "Never Married"
}
],
"text": "未婚"
}
可以把Coding和CodeableConcept的差異簡化成:
為什麼需要一個以上的Coding?
同一個醫療概念可能同時對應:
CodeableConcept可以將這些對應同時放在同一個概念中。
Quantity用來表達具有測量單位的數值。
例如體重:
"valueQuantity": {
"value": 60.2,
"unit": "kg",
"system": "http://unitsofmeasure.org",
"code": "kg"
}
常見欄位包括:
| 欄位 | 用途 |
|---|---|
value |
數值 |
comparator |
大於、小於等比較符號 |
unit |
顯示給人看的單位 |
system |
單位代碼系統 |
code |
系統處理的單位代碼 |
"unit": "kg"
主要提供人類閱讀。
"code": "kg"
則是搭配指定的system供電腦進行標準化處理。
FHIR常使用UCUM表示測量單位,其URI為:
http://unitsofmeasure.org
只寫:
"value": 60.2
無法知道是公斤、磅還是其他單位,因此測量資料通常要同時提供數值與單位。
Period用來表示具有開始及結束的時間區間。
例如一次住院期間:
"period": {
"start": "2026-09-01T08:00:00+08:00",
"end": "2026-09-03T15:00:00+08:00"
}
其中:
start:開始時間end:結束時間Period可以應用在:
如果事件尚未結束,Period也可能只有start,沒有end。
Reference用來建立Resource之間的關係。
例如,一筆Observation要指出資料屬於哪一位病人:
"subject": {
"reference": "Patient/patient-example",
"display": "王小明"
}
常見欄位包括:
| 欄位 | 用途 |
|---|---|
reference |
指向另一筆Resource |
type |
目標Resource類型 |
identifier |
使用業務識別碼指出對象 |
display |
提供人類閱讀的文字 |
在這個範例中:
"reference": "Patient/patient-example"
是實際指向Patient Resource的連結。
"display": "王小明"
只是方便人類閱讀,不能只靠姓名建立資料關係,因為不同病人可能擁有相同姓名。
Reference會在Day 11進一步介紹。
下面三個值在JSON中都是String:
"王小明"
"2000-01-01"
"male"
但是放到FHIR欄位後,可能代表不同FHIR資料型別:
| FHIR欄位 | JSON呈現 | FHIR資料型別 |
|---|---|---|
text |
"王小明" |
string |
birthDate |
"2000-01-01" |
date |
gender |
"male" |
code |
所以只看JSON外觀還不夠,仍然需要查閱FHIR規範,確認欄位要求的FHIR資料型別。
開啟FHIR Resource的官方頁面後,可以看到欄位結構表。
以Patient為例,可能看到:
Patient.identifier Identifier
Patient.name HumanName
Patient.telecom ContactPoint
Patient.gender code
Patient.birthDate date
Patient.address Address
左邊是欄位名稱,右邊是資料型別。
有些欄位旁邊還會出現:
0..1
或:
0..*
這不是資料型別,而是Cardinality,也就是欄位允許出現的次數。
例如:
0..1:可以不出現,最多出現一次。0..*:可以不出現,也可以出現很多次。1..1:必須出現一次。1..*:至少出現一次,也可以出現很多次。Cardinality和資料型別是不同概念:
| 資料型別 | 主要用途 | 範例 |
|---|---|---|
| boolean | 是或否 | true |
| integer | 整數 | 1 |
| decimal | 數值 | 37.2 |
| string | 一般文字 | "王小明" |
| code | 規範限制的代碼 | "male" |
| uri | 識別系統或規範位置 | "https://example.org" |
| date | 日期 | "2000-01-01" |
| dateTime | 日期及時間 | "2026-09-03T09:30:00+08:00" |
| Identifier | 病歷號等識別資料 | system+value |
| HumanName | 人名 | family+given |
| Address | 地址 | text+city+country |
| ContactPoint | 聯絡方式 | system+value |
| Coding | 一組標準代碼 | system+code+display |
| CodeableConcept | 可由多組代碼表達的概念 | coding+text |
| Quantity | 數值與單位 | value+unit+code |
| Period | 時間區間 | start+end |
| Reference | 連結另一筆Resource | reference+display |
請觀察以下Observation片段:
{
"resourceType": "Observation",
"status": "final",
"subject": {
"reference": "Patient/patient-example",
"display": "王小明"
},
"effectiveDateTime": "2026-09-03T09:30:00+08:00",
"valueQuantity": {
"value": 37.2,
"unit": "°C",
"system": "http://unitsofmeasure.org",
"code": "Cel"
}
}
可以找出:
status使用code。subject使用Reference。effectiveDateTime使用dateTime。valueQuantity使用Quantity。value是decimal。unit提供人類閱讀的單位。system及code提供標準化的單位資訊。從這個例子可以看出,一筆看似簡單的「體溫37.2°C」,其實需要多種資料型別共同表達。
今天認識了FHIR的常見資料型別。
基本型別通常表示單一值,例如boolean、integer、decimal、string、code、uri、date及dateTime。
複合型別則由多個欄位組成,例如Identifier、HumanName、Address、ContactPoint、Coding、CodeableConcept、Quantity、Period及Reference。
我認為今天最重要的觀念是:
FHIR資料型別不只是規定資料看起來像什麼,也在規定資料的結構及意義。
即使兩個值在JSON中都是String,在FHIR中也可能分別是date、code或uri,並受到不同規則限制。
下一篇會從今天最後介紹的Reference繼續,看看Patient、Encounter、Observation等不同Resource如何互相連結。
Day 11|FHIR Resource如何互相連結?
HL7 FHIR R4:Data Types
https://hl7.org/fhir/R4/datatypes.html
HL7 FHIR R4:References
https://hl7.org/fhir/R4/references.html
HL7 FHIR R4:Patient Resource
https://hl7.org/fhir/R4/patient.html
HL7 FHIR R4:Observation Resource
https://hl7.org/fhir/R4/observation.html
HL7 FHIR R4:UCUM Units
https://hl7.org/fhir/R4/valueset-ucum-units.html